package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import javax.swing.SwingUtilities;

/**
 * @author papq
 * Core of client. Business part of application.
 */
public class Core {

	Socket server;
	Scanner tIn = new Scanner(System.in);
	private OutputStream out;
	private InputStream in;
	private BufferedReader br;
	private PrintWriter pw;
	private String messageFromServer = "";
	private String newMessageFromServer = "";
	private Thread serverListener;

	String roomID = "";
	String playerID = "";
	String playersInGame = "";
	String bankroll = "";
	String smallBlind = "";
	String bigBlind = "";

	/**
	 * Connect to server.
	 * @param host server IP address
	 * @param port number of port to connect
	 */
	public void connectToServer(String host, int port)
			throws ConnectionFailureException {
		try {
			System.out.println("Connecting...");
			server = new Socket(host, port);
			System.out.println("Connected");
			in = server.getInputStream();
			out = server.getOutputStream();
			InputStreamReader isr = new InputStreamReader(in);
			br = new BufferedReader(isr);
			// PrintWriter pw = new PrintWriter(out);
		} catch (UnknownHostException e) {
			System.out.println("Unknown Host");
			throw new ConnectionFailureException();
		} catch (IOException e) {
			System.out.println("IO Connection failure");
			throw new ConnectionFailureException();
		}
	}

	/**
	 * Method that returns message from server which contains some parameters that should be split and save in model.
	 * @return content of message from server which contains parameters
	 */
	public String getParameters() {
		return messageFromServer;
	}
	
	/**
	 * Method that returns message that should be displayed to user in view.
	 * @return content of message to display
	 */
	public String getMessageToDisplay() {
		String operationCode = messageFromServer.substring(4, 6);
		switch (operationCode) {
		case "01":
			messageFromServer = "Hello Player "
					+ messageFromServer.substring(8, 9) + "!"
					+ " Starting game for " + messageFromServer.split(",")[1]
					+ " players.";
			break;
		case "02":
//			System.out.println("aaa" + messageFromServer);
			messageFromServer = "Player " + messageFromServer.substring(8, 9)
					+ " has joined the game. Wainting for "
					+ messageFromServer.substring(10, 11) + " player(s).";
			break;
		case "30":
			messageFromServer = messageFromServer.substring(8,
					messageFromServer.length() - 1);
			break;
		default:
			System.out.println("I'm in default. core.readFromServer()");
		}
		return messageFromServer;
	}

	/**
	 * Read first message from server.
	 * Method that returns operation code that says what to do with content of message from server.
	 * Message from server is contained in messageFromServer.
	 * @return code of operation
	 */
	public String checkOperationCode() throws ConnectionFailureException {
		try {
			messageFromServer = br.readLine();
			// System.out.println(messageFromServer);
			return messageFromServer.substring(4, 6);
		} catch (IOException e) {
			System.out.println("IO Connection failure");
			throw new ConnectionFailureException();
		} catch (NullPointerException e) {
			System.out.println("Null Pointer failure");
			throw new ConnectionFailureException();
		}
	}
	
	/**
	 * Method that returns operation code that says what to do with content of message from server.
	 * @param messageFromServer  content of message from server
	 * @return code of operation
	 */
	public String checkOperationCode(String messageFromServer) {
		this.messageFromServer = messageFromServer;
		return messageFromServer.substring(4, 6);
	}
	
	/**
	 * Method to disconnect user from server.
	 * @return text "Disconnected" which displays in view to confirm user about successful disconnection
	 */
	public String disconnectFromServer() throws ConnectionFailureException {
		try {
			server.close();
			return "Disconnected";
		} catch (IOException e) {
			System.out.println("No connection to close");
			throw new ConnectionFailureException();
		}
	}
	
	/**
	 * Method to wait for message from server in another thread. Another things can happen in meantime.
	 * @param controller necessary to notify controller about new received message
	 */
	public void getMessage(final Notificable controller)
			throws ConnectionFailureException {
		serverListener = new Thread(new Runnable() {

			/**
			 * Method to run thread serverListener.
			 */
			@Override
			public void run() {
				try {
					newMessageFromServer = br.readLine();
					if (newMessageFromServer.equals("null")) {
						serverListener.interrupt();
					}
					SwingUtilities.invokeLater(new Runnable() {

						@Override
						public void run() {
							controller.messageReceived(newMessageFromServer);
						}
					});
				} catch (IOException e) {
					System.out.println("Thread IO Connection failure - occurs always when we interrupt Thread");
					SwingUtilities.invokeLater(new Runnable() {

						@Override
						public void run() {
							controller.connectionFailureExceptionOccured();
						}
					});
				} catch (NullPointerException e) {
					System.out.println("Null Pointer failure");
					SwingUtilities.invokeLater(new Runnable() {

						@Override
						public void run() {
							controller.nullPointerExceptionOccured();
						}
					});
				}
			}
		});
		serverListener.start();
	}

	/**
	 * Method to stop thread serverListener.
	 */
	public void stopListen() {
		serverListener.interrupt();
	}
	
	/**
	 * Method to send message from client to server.
	 * @param messageToServer content a message to send to server
	 */
	public void sendMessage(String messageToServer) {
		pw = new PrintWriter(out);
		pw.println(messageToServer);
		pw.flush();

	}
}
